package sorter;

/**
 * @author Rutger Flohil
 * @author Serhat Sahin
 * Application made for class DDOA - Multithread and rmi
 * Hogeschool van Arnhem en Nijmegen, 2011
 */

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.rmi.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;

@SuppressWarnings("unchecked")
public class SortClient
{
	/**
	 * Main Method of the SortClient
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception
	{
		SortClient sc = new SortClient();
		sc.joinCompList();
	}
	
	/**
	 * Method to generate a comparable array of integers
	 * @param length length of the array
	 * @return c
	 */
	@SuppressWarnings("unchecked")
	private Comparable[] generateRandomIntegers(int length)
	{
		Comparable[] c = new Comparable[length];
		for(int i = 0; i<length; i++)
		{
			int g = 1+(int)(10000*Math.random());
			c[i]=g;
		}
		return c;
	}
	
	/**
	 * Method to generate a comparable array of Strings
	 * @param length
	 * @return c
	 */
	private Comparable[] generateRandomStrings(int length)
	{
		Random r = new Random();
		Comparable[] c = new Comparable[length];
		for(int i = 0; i<length; i++)
		{
			String randString;
			StringBuffer sb = new StringBuffer();
			for(int j = 0; j<r.nextInt(50)+1; j++)
			{
			int d = 'a' + (int) (Math.random() * 26);
			sb.append((char)d);
			}
			randString = sb.toString();
			c[i]=randString;
		}
		return c;
	}
	
	/**
	 * Method to call one of the above functions(generate comparable array)
	 * @param length
	 * @param type
	 * @return comparable array
	 */
	private Comparable[] generateRandom(int length, Class type)
	{
		if(type.equals(String.class))
		{
			return generateRandomStrings(length);
		}
		else if(type.equals(Integer.class))
		{
			return generateRandomIntegers(length);
		}
		else
		{
			return null;
		}
	}

	/**
	 * Function to split the given list into a number of new lists(comparable)
	 * @param l
	 * @param i
	 * @return cLists(array consisting of comparable arrays)
	 */
	public Comparable[][] spliceCompList(Comparable[] l, int i)
	{
		Comparable[][] cLists = new Comparable[i][];
		if(l[0]instanceof Integer)
		{
			int maxInt = 0;
			int listNr = 1;
			int lastListMax = 0;
			int maxInList = 0;
			int maxInListOrg = 0;
			for(int j = 0; j< l.length; j++)
			{
				if((Integer)l[j]>maxInt)
				{
					maxInt = (Integer)l[j];
				}
			}
			maxInListOrg = maxInt/i;
			maxInList = maxInListOrg;
			for(int k = 0; k<i; k++)
			{
				int listNeeded =0;
				for(int m = 0; m<l.length; m++)
				{
					if((Integer)l[m]>lastListMax&&(Integer)l[m]<=maxInList)
					{
						listNeeded++;
					}
				}
				Comparable[] tempList = new Comparable[listNeeded];
				int tempListCount=0;
				for(int m = 0; m<l.length; m++)
				{
					if((Integer)l[m]>lastListMax&&(Integer)l[m]<=maxInList)
					{
						tempList[tempListCount]=l[m];
						tempListCount++;
					}
				}
				cLists[listNr-1]=tempList;
				lastListMax=maxInList;
				maxInList = maxInListOrg*listNr;
				if(listNr==i-1)
				{
					
					maxInList = maxInt;
				}
				listNr++;
			}
		}
		if(l[0]instanceof String)
		{
			int maxInt = 0;
			int listNr = 1;
			int lastListMax = 0;
			int maxInList = 0;
			int maxInListOrg = 0;
			for(int j = 0; j< l.length; j++)
			{
				if(compStrLength(l[j])>maxInt)
				{
					maxInt = compStrLength(l[j]);
				}
			}
			maxInListOrg = maxInt/i;
			maxInList = maxInListOrg;
			for(int k = 0; k<i; k++)
			{
				int listNeeded =0;
				for(int m = 0; m<l.length; m++)
				{
					if(compStrLength(l[m])>lastListMax&&compStrLength(l[m])<=maxInList)
					{
						listNeeded++;
					}
				}
				Comparable[] tempList = new Comparable[listNeeded];
				int tempListCount=0;
				for(int m = 0; m<l.length; m++)
				{
					if(compStrLength(l[m])>lastListMax&&compStrLength(l[m])<=maxInList)
					{
						tempList[tempListCount]=l[m];
						tempListCount++;
						
					}
				}
				cLists[listNr-1]=tempList;
				lastListMax=maxInList;
				maxInList = maxInListOrg*listNr;
				if(listNr==i-1)
				{
					
					maxInList = maxInt;
				}
				listNr++;
					
			}
		}
		return cLists;
	}
	
	/**
	 * Function to check the length of a comparable string
	 * @param c
	 * @return strLength
	 */
	public int compStrLength(Comparable c)
	{
		String temp = (String) c;
		int strLength = temp.length();
		return strLength;
	}
	
	/**
	 * Function that makes a new list, calls the split function, makes a listjoiner and makes new threads.
	 * The rest of the progress in handled in the listjoiner.
	 * @throws Exception
	 */
	public void joinCompList() throws Exception
	{
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	    long time = System.currentTimeMillis();
		Comparable[] list = generateRandom(100000, String.class);
		Comparable[][] lists = spliceCompList(list, 5);
		ListJoiner LJ = new ListJoiner(lists.length, list.length, time);
		int counter = 0;
		for(Comparable[] lst : lists)
		{
			Thread thread;
			SorterThread ST = new SorterThread(counter, lst, LJ);
			thread = new Thread(ST);
			thread.start();
			counter++;
			ST.addObserver(LJ);
		}	
	}
}


	